
#include "RtBase.h"
#include "RtHttpJsEngine.h"
#include <atlbase.h>

static LPOLESTR ConvANSI2Uincode(LPCSTR str)
{
	int CharCount = MultiByteToWideChar(CP_ACP,0,str,-1,NULL,0);
	LPOLESTR pwszCode = new WCHAR[CharCount];
	if(!pwszCode)
		return NULL;
	MultiByteToWideChar(CP_ACP,0,str,-1,pwszCode,CharCount);
	pwszCode[CharCount - 1] = 0;
	return pwszCode;
}

static LPSTR ConvUincode2ANSI(LPCOLESTR str)
{
	int CharCount = WideCharToMultiByte(CP_ACP,0,str,-1,NULL,0,NULL,NULL);
	LPSTR pwszCode = new CHAR[CharCount];
	if(!pwszCode)
		return NULL;
	WideCharToMultiByte(CP_ACP,0,str,-1,pwszCode,CharCount,NULL,NULL);
	pwszCode[CharCount - 1] = 0;
	return pwszCode;
}

static char* IWLSSLCopyString(const char* str)
{
	if(!str)
		return NULL;
	int len = strlen(str);
	char* p = new char[len + 1];
	if(!p)
		return NULL;
	strncpy(p, str, len);
	p[len] = 0;
	return p;
}

//js function define for pac
#define MYVAR	"var myIP =\"%s\";  "

#define MYPACFUNCTIONS1	\
"function dnsDomainIs(host, domain) \
{									\
    return (host.length >= domain.length && host.substring(host.length - domain.length) == domain);	\
}									\
function dnsDomainLevels(host)		\
{									\
    return host.split('.').length-1;	\
}									\
function convert_addr(ipchars) {	\
    var bytes = ipchars.split('.');	\
    var result = ((bytes[0] & 0xff) << 24) |((bytes[1] & 0xff) << 16) | ((bytes[2] & 0xff) <<  8) | (bytes[3] & 0xff);	\
    return result;					\
}									\
function isInNet(ipaddr, pattern, maskstr)	\
{											\
	var test = /^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$/;	\
	var re = new RegExp(test);			\
	var foundArray = re.exec(ipaddr);	\
	if (RegExp.lastMatch == null)		\
	{									\
		return false;					\
	}									\
	else if (test[1] > 255 || test[2] > 255 ||		\
			test[3] > 255 || test[4] > 255) {		\
		return false;								\
	}												\
	var host = convert_addr(ipaddr);				\
	var pat = convert_addr(pattern);				\
	var mask = convert_addr(maskstr);				\
	return ((host & mask) == (pat & mask));			\
}													\
function isPlainHostName(host)						\
{													\
	var re = new RegExp('\\.');						\
	return (host.search(re)==-1);					\
}	\
function dnsResolve(host)	\
{\
	return host;\
}\
function isResolvable(host) \
{	\
    var ip = dnsResolve(host);\
    return (ip != null);\
}	\
function localHostOrDomainIs(host, hostdom) \
{\
    if (isPlainHostName(host)) \
	{\
        return (hostdom.search('/^' + host + '/') != -1);\
    }\
    else {\
        return (host == hostdom);\
    }\
}\
function myIpAddress() {\
    return (myIP) ? myIP : '127.0.0.1';\
}\
function shExpMatch(url, pattern) {\
   pattern = pattern.replace(/\\./g, '\\\\.');\
   pattern = pattern.replace(/\\*/g, '.*');\
   pattern = pattern.replace(/\\?/g, '.');\
   var newRe = new RegExp('^'+pattern+'$');\
   return newRe.test(url);\
}"

#define MYPACFUNCTIONS2_W	\
"var wdays = new Array('SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT');\
var monthes = new Array('JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC');\
function weekdayRange() \
{\
    function getDay(weekday) \
    {\
        for (var i = 0; i < 6; i++) \
        {\
            if (weekday == wdays[i]) \
                return i;\
        }\
        return -1;\
    }\
    var date = new Date();\
    var argc = arguments.length;\
    var wday;\
    if (argc < 1)\
        return false;\
    if (arguments[argc - 1] == 'GMT') \
    {\
        argc--;\
        wday = date.getUTCDay();\
    } \
    else\
    {\
        wday = date.getDay();\
    }\
    var wd1 = getDay(arguments[0]);\
    var wd2 = (argc == 2) ? getDay(arguments[1]) : wd1;\
    return (wd1 == -1 || wd2 == -1) ? false : (wd1 <= wday && wday <= wd2);\
}"

#define MYPACFUNCTIONS2_D1	\
"function dateRange() \
{\
    function getMonth(name) \
    {\
        for (var i = 0; i < 6; i++) \
        {\
            if (name == monthes[i])\
                return i;\
        }\
        return -1;\
    }\
    var date = new Date();\
    var argc = arguments.length;\
    if (argc < 1) \
    {\
        return false;\
    }\
    var isGMT = (arguments[argc - 1] == 'GMT');\
    if (isGMT) {\
        argc--;\
    }\
    if (argc == 1) \
    {\
        var tmp = parseInt(arguments[0]);\
        if (isNaN(tmp)) \
        {\
            return ((isGMT ? date.getUTCMonth() : date.getMonth()) == getMonth(arguments[0]));\
        }\
        else if (tmp < 32) \
        {\
            return ((isGMT ? date.getUTCDate() : date.getDate()) == tmp);\
        }\
        else \
        {\
            return ((isGMT ? date.getUTCFullYear() : date.getFullYear()) ==tmp);\
        }\
    }"

#define MYPACFUNCTIONS2_D2	\
    "var year = date.getFullYear();\
    var date1, date2;\
    date1 = new Date(year,  0,  1,  0,  0,  0);\
    date2 = new Date(year, 11, 31, 23, 59, 59);\
    var adjustMonth = false;\
    for (var i = 0; i < (argc >> 1); i++) \
    {\
        var tmp = parseInt(arguments[i]);\
        if (isNaN(tmp)) \
        {\
            var mon = getMonth(arguments[i]);\
            date1.setMonth(mon);\
        } else if (tmp < 32) \
        {\
            adjustMonth = (argc <= 2);\
            date1.setDate(tmp);\
        } else \
        {\
            date1.setFullYear(tmp);\
        }\
    }\
    for (var i = (argc >> 1); i < argc; i++) \
    {\
        var tmp = parseInt(arguments[i]);\
        if (isNaN(tmp)) \
        {\
            var mon = getMonth(arguments[i]);\
            date2.setMonth(mon);\
        } else if (tmp < 32) \
        {\
            date2.setDate(tmp);\
        } else \
        {\
            date2.setFullYear(tmp);\
        }\
    }\
    if (adjustMonth) \
    {\
        date1.setMonth(date.getMonth());\
        date2.setMonth(date.getMonth());\
    }\
    if (isGMT) {\
    var tmp = date;\
        tmp.setFullYear(date.getUTCFullYear());\
        tmp.setMonth(date.getUTCMonth());\
        tmp.setDate(date.getUTCDate());\
        tmp.setHours(date.getUTCHours());\
        tmp.setMinutes(date.getUTCMinutes());\
        tmp.setSeconds(date.getUTCSeconds());\
        date = tmp;\
    }\
    return ((date1 <= date) && (date <= date2));\
}"

#define MYPACFUNCTIONS2_T	\
"function timeRange() {\
    var argc = arguments.length;\
    var date = new Date();\
    var isGMT= false;\
    if (argc < 1) {\
        return false;\
    }\
    if (arguments[argc - 1] == 'GMT') {\
        isGMT = true;\
        argc--;\
    }\
    var hour = isGMT ? date.getUTCHours() : date.getHours();\
    var date1, date2;\
    date1 = new Date();\
    date2 = new Date();\
    if (argc == 1) {\
        return (hour == arguments[0]);\
    } else if (argc == 2) {\
        return ((arguments[0] <= hour) && (hour <= arguments[1]));\
    } else {\
        switch (argc) {\
        case 6:\
            date1.setSeconds(arguments[2]);\
            date2.setSeconds(arguments[5]);\
        case 4:\
            var middle = argc >> 1;\
            date1.setHours(arguments[0]);\
            date1.setMinutes(arguments[1]);\
            date2.setHours(arguments[middle]);\
            date2.setMinutes(arguments[middle + 1]);\
            if (middle == 2) \
            {\
                date2.setSeconds(59);\
            }\
            break;\
        default:\
            return false;\
        }\
    }\
    if (isGMT) {\
        date.setFullYear(date.getUTCFullYear());\
        date.setMonth(date.getUTCMonth());\
        date.setDate(date.getUTCDate());\
        date.setHours(date.getUTCHours());\
        date.setMinutes(date.getUTCMinutes());\
        date.setSeconds(date.getUTCSeconds());\
    }\
    return ((date1 <= date) && (date <= date2));\
}"



#ifdef WIN32
//js
const IID CLSID_JSScript = {0xf414c260, 0x6ac0, 0x11cf, {0xb6, 0xd1, 0x0, 0xaa, 0x0, 0xbb, 0xbb, 0x58 } };//
//vb
const IID CLSID_VBScript = {0xb54f3741, 0x5b07, 0x11cf, {0xa4, 0xb0, 0x0, 0xaa, 0x0, 0x4a, 0x55, 0xe8 } };

CIWLScriptHost::CIWLScriptHost(const char* pNamedItem, HWND hWnd)
				:m_ps(NULL),m_psp(NULL),m_cref(0)
{
	m_pNamedItem = IWLSSLCopyString(pNamedItem);
	m_hWnd = hWnd;
}

CIWLScriptHost::~CIWLScriptHost()
{
	if(m_pNamedItem)
	{
		delete []m_pNamedItem;
		m_pNamedItem = NULL;
	}
	// we must first close the script engine
	StopScript();
	if(m_psp)
	{
		m_psp->Release();
		m_psp = NULL;
	}
	if(m_ps)
	{
		//m_ps->Close();
		m_ps->Release();
		m_ps = NULL;
	}

//	comment it to avoid crashing on Win95, IE6
//	CoUninitialize( );

}

HRESULT CIWLScriptHost::CreateEngine(CLSID& engineCLSID)
{
	static BOOL bCoInitialized = FALSE;
	if (!bCoInitialized)
	{
		CoInitialize(NULL);
		bCoInitialized = TRUE;
	}

	HRESULT hr = S_OK;
	hr = ::CoCreateInstance(engineCLSID, 
							NULL,
							CLSCTX_INPROC_SERVER, 
							IID_IActiveScript,
							(void**)&m_ps);
	if ( SUCCEEDED( hr ) )
	{
		// QI the IActiveScriptParse pointer
		hr = m_ps->QueryInterface(IID_IActiveScriptParse, (void**)&m_psp);
		if (FAILED(hr) )
		{
			RT_ERROR_TRACE_THIS("CIWLScriptHost::CreateEngine, QueryInterface() failed!"
				" hr=" << hr);
			m_ps->Release();
			m_ps = NULL;
			return hr;
		}
		// set the script site
		hr = m_ps->SetScriptSite(this);
		if ( FAILED( hr ) ) {
			RT_ERROR_TRACE_THIS("CIWLScriptHost::CreateEngine, SetScriptSite() failed!"
				" hr=" << hr);
			return hr;
		}
		m_ps->SetScriptState(SCRIPTSTATE_INITIALIZED);
		// initiate the script engine
		hr = m_psp->InitNew();
		if ( FAILED( hr ) ) {
			RT_ERROR_TRACE_THIS("CIWLScriptHost::CreateEngine, InitNew() failed!"
				" hr=" << hr);
			return hr;
		}
		
/*		USES_CONVERSION;
		LPCOLESTR pNamedItem = T2OLE(m_pNamedItem);

		hr = m_ps->AddNamedItem(pNamedItem,
								SCRIPTITEM_ISVISIBLE  |  SCRIPTITEM_ISSOURCE | SCRIPTITEM_CODEONLY );
		if(FAILED(hr))
			return hr;*/

		hr = m_ps->SetScriptState(SCRIPTSTATE_STARTED);
		if ( FAILED( hr ) ) {
			RT_ERROR_TRACE_THIS("CIWLScriptHost::CreateEngine, SetScriptState() failed!"
				" hr=" << hr);
		}
	}
	else {
		RT_ERROR_TRACE_THIS("CIWLScriptHost::CreateEngine, CoCreateInstance() failed!"
			" hr=" << hr);
	}

	return hr;
}

HRESULT CIWLScriptHost::CreateScriptEngine()
{
	if(m_ps)
		return  S_FALSE;
	CLSID clsid = CLSID_JSScript;
	return CreateEngine(clsid);
}

HRESULT CIWLScriptHost::CreateScriptEngine(const char* EngineName)
{
	if(!EngineName || m_ps)
		return  S_FALSE;

	LPOLESTR wszProgID = ConvANSI2Uincode(EngineName);
	CLSID clsid;
	HRESULT hr = CLSIDFromProgID(wszProgID, &clsid);
	delete wszProgID;
	if(SUCCEEDED(hr))
		return CreateEngine(clsid);
	return hr;
}

HRESULT CIWLScriptHost::ParseScript(const char* script)
{
	if(NULL == script)
		return S_FALSE;

//	LPCOLESTR	lpostrApp = T2COLE(m_pNamedItem);
	EXCEPINFO   ei;
	LPOLESTR	lpszCode = ConvANSI2Uincode(script);

//	HRESULT hr = m_psp->ParseScriptText(lpszCode, lpostrApp, NULL, NULL, 0, 0, SCRIPTTEXT_ISVISIBLE|SCRIPTTEXT_ISPERSISTENT ,NULL, &ei);
	HRESULT hr = m_psp->ParseScriptText(lpszCode, NULL, NULL, NULL, 0, 0, 0, NULL, &ei);
	delete lpszCode;

	if (FAILED(hr)) {
		RT_ERROR_TRACE_THIS("CIWLScriptHost::ParseScript, ParseScriptText() failed!"
			"hr=" << hr << " lpszCode=" << lpszCode);
	}
	return hr;
}

HRESULT CIWLScriptHost::CallFunction(const char* funcname,
									  DISPPARAMS* params,
									  VARIANT* result)
{
	if(!m_ps || !funcname)
		return S_FALSE;

	IDispatch *pDisp = 0;
//	LPCOLESTR pNamedItem = ConvANSI2Uincode(m_pNamedItem);
//	HRESULT hr = m_ps->GetScriptDispatch(pNamedItem, &pDisp);
//	delete pNamedItem;

	HRESULT hr = m_ps->GetScriptDispatch(NULL, &pDisp);
	if(FAILED(hr))
		return hr;
	
	LPOLESTR szFunc = ConvANSI2Uincode(funcname);
	DISPID dispid;
//	INFOTRACE("CIWLScriptHost::CallFunction, GetIDsOfNames");
	hr = pDisp->GetIDsOfNames(IID_NULL, &szFunc, 1, LOCALE_SYSTEM_DEFAULT, &dispid);

	if(FAILED(hr))
	{
		pDisp->Release();
		delete szFunc;
		return hr;
	}

//	INFOTRACE("CIWLScriptHost::CallFunction, Invoke begin. hr=" << hr);
	hr = pDisp->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
							   params, result, 0, 0);
	pDisp->Release();
//	INFOTRACE("CIWLScriptHost::CallFunction, Invoke end. hr=" << hr);
	delete szFunc;
	return hr;
}

HRESULT CIWLScriptHost::RunScript()
{
	HRESULT hr = S_FALSE;
	if(m_ps)
		hr = m_ps->SetScriptState(SCRIPTSTATE_CONNECTED);
	if (FAILED(hr)) {
		RT_ERROR_TRACE_THIS("CIWLScriptHost::RunScript, SetScriptState() failed!"
			"hr=" << hr);
	}
	return hr;
}

HRESULT CIWLScriptHost::StopScript()
{
	HRESULT hr = S_FALSE;
	if(m_ps)
		hr = m_ps->SetScriptState(SCRIPTSTATE_DISCONNECTED);
	if (FAILED(hr)) {
		RT_ERROR_TRACE_THIS("CIWLScriptHost::StopScript, SetScriptState() failed!"
			"hr=" << hr);
	}
	return hr;
}

HRESULT CIWLScriptHost::ParseFile(const char* pszFileName)
{
	return S_OK;
}

STDMETHODIMP CIWLScriptHost::QueryInterface(REFIID riid,void** ppv)
{
	if (riid == IID_IUnknown||riid == IID_IActiveScriptSite)
		*ppv = (IActiveScriptSite*)this;
	else if (riid == IID_IActiveScriptSiteWindow)
		*ppv = (IActiveScriptSiteWindow*)this;
	else 
		return (*ppv = 0), E_OUTOFMEMORY;
	((IUnknown*)*ppv)->AddRef();
	return S_OK;
}

STDMETHODIMP_(ULONG) CIWLScriptHost::AddRef()
{
	return InterlockedIncrement(&m_cref);
}

STDMETHODIMP_(ULONG) CIWLScriptHost::Release()
{
	if (InterlockedDecrement(&m_cref))
		return m_cref;
	delete this;
	return 0;
}

STDMETHODIMP CIWLScriptHost::GetItemInfo(LPCOLESTR pstrName,
										DWORD dwReturnMask,
										IUnknown  * *ppiunkItem,
										ITypeInfo  * *ppti) 
{
	return TYPE_E_ELEMENTNOTFOUND ;
    /*HRESULT hr = E_FAIL;
    if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
        *ppiunkItem = 0;
    if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
        *ppti = 0;
	
	USES_CONVERSION;
	LPCOLESTR	pNamedItem = T2COLE(m_pNamedItem);
    
	if (wcscmp(pstrName, pNamedItem) == 0) {
        if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
			return S_OK;        
        if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
			return S_OK;
    }
    return hr;*/
}

STDMETHODIMP CIWLScriptHost::OnScriptError(IActiveScriptError *pscripterror) 
{
/*    DWORD dwCookie;
    LONG nChar;
    ULONG nLine;
    BSTR bstr = 0;
    EXCEPINFO ei; ZeroMemory(&ei, sizeof(ei));
    pscripterror->GetSourcePosition(&dwCookie, &nLine, &nChar);
    pscripterror->GetSourceLineText(&bstr);
    pscripterror->GetExceptionInfo(&ei);
    
    OLECHAR wszOutput[1024];
    swprintf(wszOutput, OLESTR("%s\n[Line: %d] %s\n%s"),
              ei.bstrSource, nLine, ei.bstrDescription,
              bstr ? bstr : OLESTR(""));

    SysFreeString(bstr);
    SysFreeString(ei.bstrSource);
    SysFreeString(ei.bstrDescription);
    SysFreeString(ei.bstrHelpFile);*/
    return S_OK;
}

STDMETHODIMP CIWLScriptHost::GetLCID(LCID *plcid)
{ 
	return E_NOTIMPL ; 
}

STDMETHODIMP CIWLScriptHost::GetDocVersionString(BSTR *pbstrVersion) 
{ 
	return E_NOTIMPL ;
}

STDMETHODIMP CIWLScriptHost::OnScriptTerminate(const VARIANT *pvr, const EXCEPINFO *pei)
{ 
	return S_OK; 
}

STDMETHODIMP CIWLScriptHost::OnStateChange(SCRIPTSTATE ssScriptState)
{ 
	return S_OK; 
}

STDMETHODIMP CIWLScriptHost::OnEnterScript(void)
{ 
	return S_OK; 
}

STDMETHODIMP CIWLScriptHost::OnLeaveScript(void) 
{ 
	return S_OK; 
}

// IActiveScriptSiteWindow methods    
STDMETHODIMP CIWLScriptHost::GetWindow(HWND *phwnd)
{ 
	if(!phwnd || !m_hWnd)
		return E_FAIL ;
	*phwnd = m_hWnd;
	return S_OK;
}

STDMETHODIMP CIWLScriptHost::EnableModeless(BOOL)
{ 
	return S_OK;
}
#else //unix or mac

CIWLScriptHost::CIWLScriptHost()
{
	rt = NULL;
	cx = NULL;
	global = NULL;
	bCreated = FALSE;
}

CIWLScriptHost::~CIWLScriptHost()
{
	if(cx)
	{
		JS_DestroyContext(cx);
		cx = NULL;
	}
	if(rt)
	{
		JS_DestroyRuntime(rt);
		rt = NULL;
		JS_ShutDown();
	}
}

#define  WBX_JS_GC_SIZE  64L * 1024L /* pref? */
#define IWL_JS_STACK_SIZE  64L * 1024L

int CIWLScriptHost::CreateScriptEngine()
{
	if(bCreated)
		return 0;

	rt = JS_NewRuntime(IWL_JS_GC_SIZE);
	if(NULL == rt)
		return -1;

	cx = JS_NewContext(rt, IWL_JS_STACK_SIZE);
	
	if(!cx)
	{
		ERRTRACE("CIWLScriptHost::CreateScriptEngine, can't create context");
		JS_DestroyRuntime(rt);
		rt = NULL;
		return -1;
	}

	static JSClass global_class = {
		"global", 0,
		JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
		JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
	};
	
	global = JS_NewObject(cx, &global_class, NULL, NULL);
	
	if(global && JS_InitStandardClasses(cx, global))
	{
//		INFOTRACE("CIWLScriptHost::CreateScriptEngine successfully");
		bCreated = TRUE;
		return 0;
	}
	ERRTRACE("CIWLScriptHost::CreateScriptEngine failure");
	JS_DestroyContext(cx);
	cx = NULL;
	JS_DestroyRuntime(rt);
	rt = NULL;
	return -1;
}

int CIWLScriptHost::ParseScript(const char* pacscript, char*& ret)
{
	if(!bCreated || !pacscript)
		return -1;
	
	JSBool ok;
	jsval val;
	int len = strlen(pacscript);
	ok = JS_EvaluateScript(cx, global, pacscript, len, NULL, 0, &val);
	if(!ok)
	{
		ERRTRACE("CIWLScriptHost::ParseScript, can't parse script");
		return -1;
	}
	JSString* str = JS_ValueToString(cx, val);
	if(!str)
	{
		ret = NULL;
		return 0;
	}

	DWORD strlength = JS_GetStringLength(str);
	char* pGet = new char[strlength + 1];
	if(!pGet)
		return -1;
	strcpy(pGet, JS_GetStringBytes(str));
	pGet[strlength] = 0;
	ret = pGet;
	return 0;	
}

#endif

CIWLAutoConfigJSParser::CIWLAutoConfigJSParser()
{
	m_pScriptEngine = NULL;
	m_bInitialized = FALSE;
	m_bSetPacScript = FALSE;
#ifndef WIN32
	m_strScript = NULL;
	m_strAllScript = NULL;
#endif
}

CIWLAutoConfigJSParser::~CIWLAutoConfigJSParser()
{
	if(m_pScriptEngine)
	{
#ifdef WIN32
		m_pScriptEngine->Release();
#else
		delete m_pScriptEngine;
#endif
		m_pScriptEngine = NULL;
	}
#ifndef WIN32
	if(m_strScript)
	{
		delete []m_strScript;
		m_strScript = NULL;
	}
	if(m_strAllScript)
	{
		delete []m_strAllScript;
		m_strAllScript = NULL;
	}
#endif
}

int CIWLAutoConfigJSParser::Init()
{
	if(m_bInitialized)
		return 0;
	
	m_bInitialized = TRUE;
#ifdef WIN32
	m_pScriptEngine = new CIWLScriptHost("IWL_http_client_js_parser");
	if(!m_pScriptEngine)
		return -1;
	m_pScriptEngine->AddRef();

	if(FAILED(m_pScriptEngine->CreateScriptEngine()))
	{
		m_pScriptEngine->Release();
		m_pScriptEngine = NULL;
		return -1;
	}
#else
	m_pScriptEngine = new CIWLScriptHost();
	if(!m_pScriptEngine)
		return -1;
	
	if(m_pScriptEngine->CreateScriptEngine()!=0)
	{
		delete m_pScriptEngine;
		m_pScriptEngine = NULL;
		return -1;
	}
#endif
	return 0;
}

BOOL CIWLAutoConfigJSParser::CanParserScript()
{
	return (m_bInitialized && m_pScriptEngine);
}

int CIWLAutoConfigJSParser::SetPacScript(const char* script)
{
	if(NULL == script /*|| !strstr(script, "FindProxyForURL")*/)
		return -1;

	if(m_bSetPacScript)
		return 0;
#ifdef WIN32	
	char fucntions[10240];
	sprintf(fucntions, MYVAR "\n%s\n%s\n%s\n%s\n%s\n", GetLocalIPAddress(), 
		MYPACFUNCTIONS1,
		MYPACFUNCTIONS2_W,
		MYPACFUNCTIONS2_D1,
		MYPACFUNCTIONS2_D2,
		MYPACFUNCTIONS2_T);

	HRESULT hr = m_pScriptEngine->ParseScript(fucntions);	
	if(FAILED(hr))
		return -1;
	
	hr = m_pScriptEngine->ParseScript(script);
	if(FAILED(hr))
		return -1;
	
	hr = m_pScriptEngine->RunScript();
	if(FAILED(hr))
		return -1;
#else
	m_strScript = IWLSSLCopyString(script);
//	INFOTRACE("pac script="<<m_strScript);
	if(!m_strScript)
		return -1;
#endif
	
	m_bSetPacScript = TRUE;
	return 0;
}

int CIWLAutoConfigJSParser::FindProxyFromURL(
									const char* url,
									const char* host,
									char*& proxyresult)
{
//	host = ResolveIP(host);
//	if(!host)
//		return -1;

#ifdef WIN32

	OLECHAR* oleurl = ConvANSI2Uincode(url);
	BSTR bstrurl = ::SysAllocString(oleurl);
	OLECHAR* oleip = ConvANSI2Uincode(host);
	BSTR bstrip = ::SysAllocString(oleip);
		
	VARIANT vt[2];
	vt[0].vt = VT_BSTR;
	vt[0].bstrVal = bstrip;
	vt[1].vt = VT_BSTR;
	vt[1].bstrVal = bstrurl;
	DISPPARAMS dispParamArgs={vt,NULL,2,0};

	VARIANT var;
	HRESULT hr = m_pScriptEngine->CallFunction("FindProxyForURL", &dispParamArgs, &var);

	delete oleurl;
	oleurl = NULL;
	delete oleip;
	oleip = NULL;
	::SysFreeString(bstrurl);
	bstrurl = NULL;
	::SysFreeString(bstrip);
	bstrip = NULL;

	if(FAILED(hr)) {
		RT_ERROR_TRACE_THIS("CIWLAutoConfigJSParser::FindProxyFromURL,"
			" CallFunction() failed! "
			" hr=" << hr << 
			" url=" << url << 
			" host=" << host);
		return -1;
	}

	char* p = ConvUincode2ANSI( var.bstrVal);
	proxyresult = IWLSSLCopyString(p);
	delete p;

#else
#define CALLFUNC	"FindProxyForURL(\"%s\",\"%s\");"
	if(!m_strAllScript)
	{
		if(!m_strScript)
			return -1;
		m_iAllLen = strlen(m_strScript) + 10240;
		m_strAllScript = new char[m_iAllLen];
	}
	memset(m_strAllScript, 0, m_iAllLen);
	sprintf(m_strAllScript,MYVAR "\n%s\n%s\n%s\n%s\n%s\n%s\n" CALLFUNC, GetLocalIPAddress(), 
		MYPACFUNCTIONS1,
		MYPACFUNCTIONS2_W,
		MYPACFUNCTIONS2_D1,
		MYPACFUNCTIONS2_D2,
		MYPACFUNCTIONS2_T,
		m_strScript,
		url, host);

	return m_pScriptEngine->ParseScript(m_strAllScript, proxyresult);
#endif
	return 0;
}

LPCSTR CIWLAutoConfigJSParser::GetLocalIPAddress() 
{
	char achBuf[256];
	achBuf[0] = 0;

	if(gethostname(achBuf, sizeof(achBuf)) == 0)
	{
		struct hostent* pHost = gethostbyname(achBuf);

		if(pHost)
		{
			struct in_addr in;
			memcpy(&in.s_addr, pHost->h_addr, pHost->h_length);
			char* addr = inet_ntoa(in);
			return addr;
		}
	}
	return "127.0.0.1";	
}

LPCSTR CIWLAutoConfigJSParser::ResolveIP(LPCSTR pHostName) 
{
	if (!pHostName)
		return pHostName;
	
	unsigned long lip = inet_addr(pHostName);
	if (lip != INADDR_NONE)
		return pHostName;

	char* lpszTemp = NULL;
	struct hostent* he = gethostbyname((char*)pHostName);
	if(he) 
	{
		lpszTemp = inet_ntoa((in_addr&)(*he->h_addr_list[0]));
	}
	return lpszTemp;
}
